package org.jasig.cas.client.authentication.sdk;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jasig.cas.client.authentication.AttributePrincipalImpl;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.AssertionImpl;
import org.jasig.cas.client.validation.TicketValidationException;

/**
 * 
 * @author CreGu
 * 
 */
public class ApiRpc {
	protected static final org.slf4j.Logger log = org.slf4j.LoggerFactory
			.getLogger(ApiRpc.class);

	public static final String SERVICETICKET = "serviceTicket";
	public static final String TICKETGRANTINGTICKET = "ticketGrantingTicket";

	private final ApiCaller caller;

	public ApiRpc(ApiCaller caller) {
		this.caller = caller;
	}

	public void casLogin(String username, String password,
			HttpServletRequest request, HttpServletResponse response)
			throws TicketValidationException {

		Map<String, String> params = new HashMap<String, String>();

		CommonUtils.assertNotNull(username, "username not null");
		CommonUtils.assertNotNull(password, "password not null");

		try {
			params.put("username", username);
			params.put("password", password);

			String urlSuffix = "login";
			caller.setUrlSuffix(urlSuffix);
			final String serverResponse = caller.apiCall(params);

			if (serverResponse == null) {
				throw new TicketValidationException(
						"The CAS server returned no response.");
			}

			log.debug("Server response: {}", serverResponse);

			final String error = XmlUtils.getTextForElement(serverResponse,
					"authenticationFailure");

			if (CommonUtils.isNotBlank(error)) {
				throw new TicketValidationException(error);
			}

			final String serviceTicket = XmlUtils.getTextForElement(
					serverResponse, SERVICETICKET);
			final String ticketGrantingTicket = XmlUtils.getTextForElement(
					serverResponse, TICKETGRANTINGTICKET);

			validateServiceTicket(serviceTicket, ticketGrantingTicket);

			params.put(TICKETGRANTINGTICKET, ticketGrantingTicket);
			caller.redirect(request, response, params);
		} catch (final MalformedURLException e) {
			throw new TicketValidationException(e);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	protected Assertion validateServiceTicket(String serviceTicket,
			String ticketGrantingTicket) throws TicketValidationException {
		Map<String, String> params = new HashMap<String, String>();
		CommonUtils.assertNotNull(serviceTicket, "serviceTicketId not null");
		try {
			params.put("ticket", serviceTicket);

			caller.setUrlSuffix("serviceValidate");
			final String serverResponse = caller.apiCall(params);

			if (serverResponse == null) {
				throw new TicketValidationException(
						"The CAS server returned no response.");
			}

			final String error = XmlUtils.getTextForElement(serverResponse,
					"authenticationFailure");

			if (CommonUtils.isNotBlank(error)) {
				throw new TicketValidationException(error);
			}

			final String principal = XmlUtils.getTextForElement(serverResponse,
					"user");
			Map<String, Object> attributes = new HashMap<String, Object>();
			attributes.put(TICKETGRANTINGTICKET, ticketGrantingTicket);

			Assertion assertion = new AssertionImpl(new AttributePrincipalImpl(
					principal, attributes));
			return assertion;
		} catch (final MalformedURLException e) {
			throw new TicketValidationException(e);
		}
	}

	public ApiCaller getCaller() {
		return caller;
	}
}